package com.peiqi.aiproject.controller;

import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.peiqi.aiproject.domain.vo.ResponseVO;
import com.peiqi.aiproject.service.MessageService;
import io.reactivex.Flowable;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import static com.peiqi.aiproject.domain.vo.ResponseVO.success;

/**
 * AI聊天接口
 */
@RestController
@RequestMapping("/api/message")
public class MessageController {
    @Resource
    MessageService messageService;
    /**
     * 通过POST请求向服务器发送问题，并以流的形式返回答案。
     *
     * @param question 用户提出的问题，作为请求体的内容。
     * @param response HTTP响应对象，用于在发生错误时输出错误信息。
     * @return 返回一个Flux流，该流包含服务器发送的事件，事件数据部分为问题的回答内容。
     * @throws NoApiKeyException      如果没有API密钥，抛出此异常。
     * @throws InputRequiredException 如果缺少输入，抛出此异常。
     */
    @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<String>> aiTalk(@RequestBody String question, HttpServletResponse response)
            throws NoApiKeyException, InputRequiredException {
        Flowable<GenerationResult> result  = messageService.sendMessageStream(question);

        // 处理AI生成的结果，并通过ServerSentEvent返回
        return Flux.from(result)
                .map(m -> {
                    // 提取生成的回答内容
                    String content = m.getOutput().getChoices().get(0).getMessage().getContent();
                    return ServerSentEvent.<String>builder().data(content).build();
                })
                .publishOn(Schedulers.boundedElastic())
                .doOnError(e -> {
                    // 在异常发生时，向客户端发送错误信息
                    Map<String, Object> map = new HashMap<>() {{
                        put("code", "400");
                        put("message", "出现了异常，请稍后重试");
                    }};
                    try {
                        response.getWriter().print(JSONUtil.toJsonStr(map));
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                });
    }

    @PostMapping(value = "/send-websocket")
    public ResponseVO<String> aiSend(@RequestBody String question)
            throws InterruptedException {
        messageService.sendMessage(question);
        return success(HttpStatus.HTTP_CREATED,"发送成功");
    }
}
